#include "stdafx.h"
#include "GlobalFunctionImpl.h"

#include "PtrDispatch.h"
#include "afxinet.h"
#include "comutil.h"
#include "strsafe.h"

CGlobalFunctionImpl::CGlobalFunctionImpl()
{
	ZeroMemory(&m_init, sizeof(m_init));
	_GVLoadFile();
}

CGlobalFunctionImpl::~CGlobalFunctionImpl()
{
	_GVSaveFile();
}

BOOL CGlobalFunctionImpl::Init( PGFINIT p )
{
	if (NULL==p)
		return FALSE;

	m_init = *p;
	return TRUE;
}

BOOL CGlobalFunctionImpl::GetGlobalValue( LPCSTR szKey, PGFSTRING pszValue )
{
	if (NULL==szKey || NULL==pszValue)
		return FALSE;
	
	MAP_KEY_VALUE::iterator it = m_map.find(szKey);
	if (m_map.end() != it)
	{
		pszValue->pfnSetString(pszValue, it->second.c_str());
		return TRUE;
	}
	return FALSE;
}

void CGlobalFunctionImpl::SetGlobalValue( LPCSTR szKey, LPCWSTR szValue )
{
	if (NULL==szKey || NULL==szValue)
		return;
	
	MAP_KEY_VALUE::value_type value = MAP_KEY_VALUE::value_type(szKey, szValue);
	m_map.insert(value);
}

void CGlobalFunctionImpl::DelGlobalValue( LPCSTR szKey )
{
	if (NULL==szKey)
		return;
	
	m_map.erase(szKey);
}

HGFINTERNETSESSION CGlobalFunctionImpl::CreateInternetSession()
{
	return (HGFINTERNETSESSION)new CInternetSession(_T("Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)"));
}

void CGlobalFunctionImpl::DestroyInternetSession(HGFINTERNETSESSION hSession)
{
	if (hSession)
		delete (CInternetSession*)hSession;
}

BOOL CGlobalFunctionImpl::CreateDispatchAndAttachInternetSession(HGFINTERNETSESSION hSession, IDispatch** ppDisp)
{
	if (NULL==hSession || NULL==ppDisp)
		return FALSE;

	typedef CPtrDispatchT<CInternetSession> CDispatch_InternetSession;
	CDispatch_InternetSession* p = new CDispatch_InternetSession;
	p->GetPtr() = (CInternetSession*)hSession;
	p->AddRef();
	*ppDisp = p;
	
	return TRUE;
}

HGFINTERNETSESSION CGlobalFunctionImpl::GetInternetSessionFromDispatch( IDispatch* pDisp )
{
	if (NULL==pDisp)
		return NULL;

	DISPPARAMS dispParam = {0};
//	_variant_t vRet;
	VARIANT vParam; vParam.vt = VT_BYREF; vParam.byref = NULL;
	dispParam.rgvarg = &vParam;
	dispParam.cArgs = 1;
	
	DISPID dispID = 0;
	CString str = _T("getPtr");
	LPOLESTR lpsz = (LPOLESTR)(LPCTSTR)str;
		
	pDisp->GetIDsOfNames(IID_NULL, &lpsz, 1, LOCALE_USER_DEFAULT, &dispID);
	pDisp->Invoke(dispID, IID_NULL, LOCALE_USER_DEFAULT,
		DISPATCH_METHOD, &dispParam, NULL, 
		NULL, NULL);
	
	CInternetSession* pRet = NULL;
	if (vParam.byref)
	{
		CInternetSession** pp = (CInternetSession**)vParam.byref;
		pRet = *pp;
	}

	VariantClear(&vParam);
	return (HGFINTERNETSESSION)pRet;
}

BOOL CGlobalFunctionImpl::OpenUrl( PGFOPENURL p )
{
	if (NULL==p)
		return FALSE;

	CInternetSession* pIS = (CInternetSession*)p->hSession;
	if (NULL==pIS)
		return FALSE;

	DWORD dwServiceType = 0;
	INTERNET_PORT nPort = 0;
	CString strServer;
	CString strObject;
	BOOL bRet = FALSE;
	CHttpConnection* pHC = NULL;
	CHttpFile* pHF = NULL;
	DWORD dwStatusCode = 0;
	CHAR* pBuf = NULL;

	try	{
	do 
	{
		bRet = AfxParseURL(p->szUrl, dwServiceType, strServer, strObject, nPort);
		if (FALSE==bRet)
			break;

		if (AFX_INET_SERVICE_HTTP!=dwServiceType && AFX_INET_SERVICE_HTTPS!=dwServiceType)
			break;

		pHC = pIS->GetHttpConnection(strServer, nPort);
		if (NULL==pHC)
			break;

		int nVerb = CHttpConnection::HTTP_VERB_GET;
		switch (p->nVerb)
		{
		case GFOPENURL_VERB_GET:
			break;
		case GFOPENURL_VERB_HEAD:
			nVerb = CHttpConnection::HTTP_VERB_HEAD;
			break;
		case GFOPENURL_VERB_POST:
			nVerb = CHttpConnection::HTTP_VERB_POST;
			break;
		}

		LPCTSTR arr[] = {_T("*/*"), NULL};
		
		pHF = pHC->OpenRequest(nVerb, strObject, p->szRefer, 1, arr, NULL, INTERNET_FLAG_EXISTING_CONNECT);
		if (NULL==pHF)
			break;

		bRet = pHF->SendRequest(p->szHeader, wcslen(p->szHeader), (LPVOID)p->szData, strlen(p->szData));

		if (pHF->QueryInfoStatusCode(dwStatusCode) && dwStatusCode>=200 && dwStatusCode < 300 && 0!=p->nResultCodepage)
		{
			pBuf = new CHAR[8*1024 + 1];
			std::string str;
			DWORD dw = 0;
			
			while(dw = pHF->Read(pBuf, 8*1024))
			{
				pBuf[dw] = 0;
				str += pBuf;
			}

#if 0
OutputDebugString(p->szUrl);
CFile file;
file.Open(L"C:\\Temp.htm", CFile::modeCreate|CFile::modeWrite|CFile::typeBinary);
file.Write(str.c_str(), str.length());
file.Close();
#endif

			int nLen = MultiByteToWideChar(p->nResultCodepage, 0, str.c_str(), str.length(), 0, NULL);
			WCHAR* pBuf = p->szResult.pfnAllocBuffer(&p->szResult, nLen);
			MultiByteToWideChar(p->nResultCodepage, 0, str.c_str(), str.length(), pBuf, nLen);
			p->szResult.pfnReleaseBuffer(&p->szResult, pBuf);
			bRet = TRUE;
		}
	} while (0);
	} catch (...) {}

	if (pBuf)
		delete [] pBuf;

	return bRet;
}

void CGlobalFunctionImpl::_GVLoadFile()
{
	if (FALSE==PathFileExists(_GVGetFileName()))
		return;

	try
	{
		CFile file(_GVGetFileName(),
			CFile::modeRead | CFile::typeBinary | CFile::shareDenyNone);
		CArchive ar(&file, CArchive::load);
		
		size_t nSize = 0;
		ar >> nSize;
		
		for (size_t i = 0; i < nSize; i++)
		{
			CString strKey;
			CString strValue;
			ar >> strKey >> strValue;
			std::string str = (LPCSTR)_bstr_t(strKey);
			MAP_KEY_VALUE::value_type value = MAP_KEY_VALUE::value_type(str, (LPCWSTR)strValue);
			m_map.insert(value);
		}
	}
	catch (...)
	{
	}
}

void CGlobalFunctionImpl::_GVSaveFile()
{
	try
	{
		CFile file(_GVGetFileName(),
			CFile::modeCreate | CFile::modeWrite | CFile::typeBinary | CFile::shareDenyNone);
		CArchive ar(&file, CArchive::store);
		
		size_t nSize = m_map.size();
		ar << nSize;
		
		MAP_KEY_VALUE::iterator it = m_map.begin();
		for (; it != m_map.end(); it++)
		{
			CString strKey = (LPCTSTR)_bstr_t((*it).first.c_str());
			CString strValue = (*it).second.c_str();
			ar << strKey << strValue;
		}
	}
	catch (...)
	{
	}
}

CString CGlobalFunctionImpl::_GVGetFileName() const
{
	TCHAR   s[MAX_PATH] = {0} ;
	GetModuleFileName (NULL, s, MAX_PATH) ;
	PathRemoveFileSpec (s) ;
	PathAddBackslash (s) ;
	PathAppend(s, _T("gv.dat"));
	return s;
}

void CGlobalFunctionImpl::SaveGlobalValue()
{
	_GVSaveFile();
}

BOOL CGlobalFunctionImpl::AddLog( LPCWSTR lpszLog )
{
	if (lpszLog && m_init.pfnAddLog)
		return m_init.pfnAddLog(lpszLog, m_init.pContext);
	return FALSE;
}